<?php
class MvcPathCorrectorTest extends PHPUnit_Framework_TestCase {

    private $_arRules = array(
        '/incontroller/' => 'outcontroller',
        '/^index(.*)/'    => 'main/index$1'
    );


    private $_arDefaultRoutes = array(
        'controller' => 'defaultcontroller',
        'method'     => 'defaultmethod'
    );

    private $_strParamFilter = '/^[a-zA-Z0-9_\-]*$/';

    const TEST_REQUEST_CAPS                       = 'ConTroLler/MetHod/paRaM';
    const TEST_REQUEST_WHIT_GET_REQUEST           = 'controller/method/param?id=1050';
    const TEST_REQUEST_MANY_PARAMS                = 'controller/method/param/param';
    const TEST_REQUEST_WITH_STAR_END_DELIMITERS   = '/controller/method/param/';
    const TEST_REQUEST_SIMPLE_REPLACE             = 'incontroller/method/param';
    const TEST_REQUEST_REGEXP_REPLACE             = 'index/param';
    const TEST_REQUEST_INSERT_DEFAULT_METHOD      = 'controller';
    const TEST_REQUEST_WITH_ALTERNATIVE_DELIMITER = ':controller:method:param:param';
    const TEST_REQUEST_ADELIMITER_REGEXP_RULE     = 'index:param';


    const TEST_CONTROLLER_VALID_NAME   = 'Controller';
    const TEST_CONTROLLER_INVALID_NAME = 'Contr&oller';
    const TEST_CONTROLLER_CAPS_CORRECT = 'cOntROlLer';

    const TEST_METHOD_VALID_NAME = 'index';
    const TEST_METHOD_RESERVE_NAME = '_index';
    const TEST_METHOD_INVALID_NAME = 'ind$ex';
    const TEST_METHOD_CAPS_CORRECT = 'InDeX';


    /**
     * @return MVC_PathCorrector
     */
    private function _standartTestObject () {
        return new MVC_PathCorrector(
            $this->_arRules,
            $this->_arDefaultRoutes,
            $this->_strParamFilter
        );
    }


    private function _alternativeDelimiterTestObject () {
        return new MVC_PathCorrector(
            $this->_arRules,
            $this->_arDefaultRoutes,
            $this->_strParamFilter,
            ':'
        );
    }


    public function testConstructor_CorrectCreateObject () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals($this->_arRules, $objPathCorrector->getRulesForCorrectionRequest());
        $this->assertEquals($this->_arDefaultRoutes['controller'], $objPathCorrector->getDefaultRoute('controller'));
        $this->assertEquals($this->_arDefaultRoutes['method'], $objPathCorrector->getDefaultRoute('method'));
        $this->assertEquals($this->_strParamFilter, $objPathCorrector->getParamFilter());
        $this->assertEquals('/', $objPathCorrector->getRequestDelimiter());
    }


    public function testRequestCorrect_LowerRequest () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(
            'controller/method/param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_CAPS)
        );
    }


    public function testRequestCorrect_ClipGetRequest () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(
            'controller/method/param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_WHIT_GET_REQUEST)
        );
    }


    public function testRequestCorrect_ManyParams () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(
            'controller/method/param/param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_MANY_PARAMS)
        );
    }


    public function testRequestCorrect_DeletedStartEndDelimiters () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(
            'controller/method/param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_WITH_STAR_END_DELIMITERS)
        );
    }


    public function testRequestCorrect_SimpleReplaceByRule () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(
            'outcontroller/method/param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_SIMPLE_REPLACE)
        );
    }


    public function testRequestCorrect_RegexpReplaceByRule () {
        $objPathCorrector = $this->_standartTestObject();
        $this->assertEquals(
            'main/index/param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_REGEXP_REPLACE)
        );
    }


    public function testRequestCorrect_InsertDefaultController () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(
            'controller/defaultmethod',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_INSERT_DEFAULT_METHOD)
        );
    }


    public function testRequestCorrect_AlternativeDelimiter () {
        $objPathCorrector = $this->_alternativeDelimiterTestObject();

        $this->assertEquals(
            'controller:method:param:param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_WITH_ALTERNATIVE_DELIMITER)
        );
    }


    public function testRequestCorrect_AlternativeDelimiterRegExpRule () {
        $objPathCorrector = $this->_alternativeDelimiterTestObject();

        $this->assertEquals(
            'main:index:param',
            $objPathCorrector->requestCorrect(self::TEST_REQUEST_ADELIMITER_REGEXP_RULE)
        );
    }


    public function testControllerCorrect_ValidName () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(self::TEST_CONTROLLER_VALID_NAME, $objPathCorrector->controllerCorrect(self::TEST_CONTROLLER_VALID_NAME));
    }


    public function testControllerCorrect_InvalidName () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals('', $objPathCorrector->controllerCorrect(self::TEST_CONTROLLER_INVALID_NAME));
    }


    public function testControllerCorrect_CapsCorrect () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals('Controller', $objPathCorrector->controllerCorrect(self::TEST_CONTROLLER_CAPS_CORRECT));
    }


    public function testParamCorrect () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(array('param', '-1'), $objPathCorrector->paramCorrect(array('param','par&am')));
    }


    public function testMethodCorrect_ValidName () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals(self::TEST_METHOD_VALID_NAME, $objPathCorrector->methodCorrect(self::TEST_METHOD_VALID_NAME));
    }


    public function testMethodCorrect_ReserveName () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals('', $objPathCorrector->methodCorrect(self::TEST_METHOD_RESERVE_NAME));
    }


    public function testMethodCorrect_InvalidName () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals('', $objPathCorrector->methodCorrect(self::TEST_METHOD_INVALID_NAME));
    }


    public function testMethodCorrect_CapsCorrect () {
        $objPathCorrector = $this->_standartTestObject();

        $this->assertEquals('index', $objPathCorrector->methodCorrect(self::TEST_METHOD_CAPS_CORRECT));
    }
}